package com.jsu.clubmanagementsystem.service.application.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jsu.clubmanagementsystem.common.ErrorCode;
import com.jsu.clubmanagementsystem.common.PageQueryRequest;
import com.jsu.clubmanagementsystem.exception.BusinessException;
import com.jsu.clubmanagementsystem.model.dto.clubapplication.ClubApplicationAddRequest;
import com.jsu.clubmanagementsystem.model.dto.clubapplication.ClubApplicationQueryRequest;
import com.jsu.clubmanagementsystem.model.entity.*;
import com.jsu.clubmanagementsystem.model.enums.ApplicationTypeEnum;
import com.jsu.clubmanagementsystem.model.enums.ReviewResultEnum;
import com.jsu.clubmanagementsystem.model.vo.clubApplication.ClubApplicationListVO;
import com.jsu.clubmanagementsystem.model.vo.clubApplication.ClubApplicationVO;
import com.jsu.clubmanagementsystem.model.vo.club.ClubVO;
import com.jsu.clubmanagementsystem.model.vo.user.UserVO;
import com.jsu.clubmanagementsystem.model.vo.review.ReviewVO;
import com.jsu.clubmanagementsystem.service.activity.ActivityService;
import com.jsu.clubmanagementsystem.service.application.UserApplicationService;
import com.jsu.clubmanagementsystem.service.club.ClubMembershipService;
import com.jsu.clubmanagementsystem.service.club.ClubService;
import com.jsu.clubmanagementsystem.service.review.ReviewService;
import com.jsu.clubmanagementsystem.service.user.UserService;
import com.jsu.clubmanagementsystem.service.application.ClubApplicationService;
import com.jsu.clubmanagementsystem.mapper.ClubApplicationMapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
* @author 24753
* @description 针对表【club_application(社团相关申请)】的数据库操作Service实现
* @createDate 2025-06-01 22:36:13
*/
@Service
public class ClubApplicationServiceImpl extends ServiceImpl<ClubApplicationMapper, ClubApplication>
    implements ClubApplicationService{

    @Resource
    private UserService userService;

    @Resource
    private ClubService clubService;

    @Resource
    private ClubMembershipService clubMembershipService;

    @Resource
    private ActivityService activityService;

    @Resource
    private UserApplicationService userApplicationService;

    @Resource
    @Lazy
    private ReviewService reviewService;

    /**
     * 处理要添加的申请
     *
     * @param addRequest 申请请求
     * @return
     */
    @Override
    public Long processClubApplication(ClubApplicationAddRequest addRequest) {
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(addRequest.getType());
        if (applicationType == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "无效的申请类型");
        }
        switch (applicationType) {
            case CREATE_CLUB:
                return addCreateClubApplication(addRequest);
            case DELETE_CLUB:
                return addDeleteClubApplication(addRequest);
            case CHANGE_CLUB_INFO:
                return addUpdateClubApplication(addRequest);
            default:
                throw new BusinessException(ErrorCode.PARAM_ERROR, "无效的社团申请类型");
        }
    }

    /**
     * 提交成立社团申请
     *
     * @param clubApplicationAddRequest
     * @return
     */
    private Long addCreateClubApplication(ClubApplicationAddRequest clubApplicationAddRequest) {
        ClubApplication clubApplication = new ClubApplication();
        BeanUtils.copyProperties(clubApplicationAddRequest, clubApplication);
        clubApplication.setResult(ReviewResultEnum.WAITING.getCode());
        this.clubApplicationValidation(clubApplication);

        Club club = new Club();
        club.setUserId(clubApplicationAddRequest.getUserId());
        club.setClubName(clubApplicationAddRequest.getClubName());
        club.setIntroduction(clubApplicationAddRequest.getClubIntroduction());
        clubService.addClubValidation(club);

        if (this.isExist(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "已提交过申请");
        }
        if (!this.save(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return clubApplication.getId();
    }

    /**
     * 提交注销社团申请
     *
     * @param clubApplicationAddRequest
     * @return
     */
    private Long addDeleteClubApplication(ClubApplicationAddRequest clubApplicationAddRequest) {
        Long userId = clubApplicationAddRequest.getUserId();
        Long clubId = clubApplicationAddRequest.getClubId();
        if (!clubService.isExist(clubId)) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "社团不存在");
        }
        if (!clubService.isManagerOfClub(userId, clubId)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "只有本社团社长才能申请注销社团");
        }

        List<Activity> activityList = activityService.getActivityListOfClub(clubId);
        if(!activityService.isActivitiesAllEnd(activityList)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "社团有未结束的社团活动");
        }
        List<UserApplication> applicationList = userApplicationService.getAllApplicationsOfClub(clubId);
        if(!userApplicationService.isApplicationsAllReview(applicationList)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "社团有未审核的申请");
        }

        ClubApplication clubApplication = new ClubApplication();
        BeanUtils.copyProperties(clubApplicationAddRequest, clubApplication);
        clubApplication.setType(ApplicationTypeEnum.DELETE_CLUB.getCode());
        clubApplication.setResult(ReviewResultEnum.WAITING.getCode());
        if (this.isExist(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "已提交过申请，请勿重复提交");
        }
        if (!this.save(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return clubApplication.getId();
    }

    /**
     * 提交修改社团信息申请
     *
     * @param clubApplicationAddRequest
     * @return
     */
    private Long addUpdateClubApplication(ClubApplicationAddRequest clubApplicationAddRequest) {
        Long userId = clubApplicationAddRequest.getUserId();
        Long clubId = clubApplicationAddRequest.getClubId();
        Long newManagerId = clubApplicationAddRequest.getNewManagerId();
        if (clubId == null || clubId == 0){
            throw new BusinessException(ErrorCode.PARAM_ERROR, "社团编号错误");
        }
        Club club = clubService.getById(clubId);
        if (club == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "社团不存在");
        }
        if (!club.getUserId().equals(userId)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "只有本社团社长才能申请修改社团信息");
        }
        if(newManagerId != null && !newManagerId.equals(club.getUserId())){
            clubService.updateManagerValidation(newManagerId, clubId);
        }

        ClubApplication clubApplication = new ClubApplication();
        BeanUtils.copyProperties(clubApplicationAddRequest, clubApplication);
        clubApplication.setClubTags(JSONUtil.toJsonStr(clubApplicationAddRequest.getClubTags()));
        clubApplication.setResult(ReviewResultEnum.WAITING.getCode());
        this.clubApplicationValidation(clubApplication);
        if (this.isExist(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "已提交过申请，请勿重复提交");
        }
        if (!this.save(clubApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return clubApplication.getId();
    }

    /**
     * 获得封装对象
     *
     * @param clubApplication
     * @return
     */
    public ClubApplicationVO getClubApplicationVO(ClubApplication clubApplication){
        if (clubApplication == null) {
            return null;
        }
        ClubApplicationVO clubApplicationVO = ClubApplicationVO.objToVo(clubApplication);
        clubApplicationVO.setClubTags(JSONUtil.toList(clubApplication.getClubTags(), String.class));

        if (!clubApplication.getResult().equals(ReviewResultEnum.WAITING.getCode())) {
            Long applicationId = clubApplication.getId();
            Integer applicationType = clubApplication.getType();
            clubApplicationVO.setReviewVO(reviewService.getReviewVoByApplication(applicationId, applicationType));
        } else {
            ReviewVO reviewVO = new ReviewVO();
            reviewVO.setResult(ReviewResultEnum.WAITING.getInfo());
            clubApplicationVO.setReviewVO(reviewVO);
        }

        Long clubId = clubApplication.getClubId();
        Club club = clubService.getById(clubId);
        if(club == null){
            clubApplicationVO.setClubVo(null);
        } else {
            ClubVO clubVO = ClubVO.objToVo(club);
            clubApplicationVO.setClubVo(clubVO);
        }

        Long userId = clubApplication.getUserId();
        UserVO userVO = UserVO.objToVoAllInfo(userService.getById(userId));
        clubApplicationVO.setUserVo(userVO);

        Long newManagerId = clubApplication.getNewManagerId();
        if (newManagerId != null){
            UserVO newManagerVO = UserVO.objToVoAllInfo(userService.getById(newManagerId));
            clubApplicationVO.setNewManager(newManagerVO);
        }
        return clubApplicationVO;
    }

    /**
     * 查询社团申请列表
     *
     * @param clubApplicationQueryRequest
     * @return
     */
    @Override
    public Page<ClubApplicationVO> listClubApplicationVOByPage(ClubApplicationQueryRequest clubApplicationQueryRequest) {
        if (clubApplicationQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }

        Integer type = clubApplicationQueryRequest.getType();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType != null &&
                !applicationType.equals(ApplicationTypeEnum.CREATE_CLUB) &&
                !applicationType.equals(ApplicationTypeEnum.DELETE_CLUB) &&
                !applicationType.equals(ApplicationTypeEnum.CHANGE_CLUB_INFO)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "未知的申请类型");
        }

        Integer result = clubApplicationQueryRequest.getResult();
        if (result != null) {
            ReviewResultEnum reviewResult = ReviewResultEnum.getByCode(result);
            if (reviewResult == null) {
                throw new BusinessException(ErrorCode.PARAM_ERROR, "未知的审核状态");
            }
        }

        QueryWrapper<ClubApplication> queryWrapper = this.getQueryWrapper(clubApplicationQueryRequest);
        List<ClubApplicationVO> applicationVOList = this.list(queryWrapper).stream()
                .map(application -> { return this.getClubApplicationVO(application); })
                .collect(Collectors.toList());

        long current = clubApplicationQueryRequest.getCurrent();
        long size = clubApplicationQueryRequest.getPageSize();
        Page<ClubApplicationVO> clubApplicationVOPage = new Page<>(current, size);
        clubApplicationVOPage.setRecords(applicationVOList);
        return clubApplicationVOPage;
    }

    /**
     * 申请是否存在
     *
     * @param applicationId
     * @return
     */
    public boolean isExist(Long applicationId) {
        if (applicationId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        return this.getById(applicationId) != null;
    }

    /**
     * 申请是否存在
     * @param applicationId
     * @param type
     * @return
     */
    public boolean isExist(Long applicationId, Integer type) {
        if (applicationId == null || type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少参数");
        }
        ClubApplication application = this.getById(applicationId);
        if (application != null) {
            return application.getType() == type;
        }
        return false;
    }

    /**
     * 申请是否已存在
     *
     * @param clubApplication 申请对象
     * @return 是否存在
     */
    @Override
    public boolean isExist(ClubApplication clubApplication) {
        if (clubApplication == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        Long clubId = clubApplication.getClubId();
        Long userId = clubApplication.getUserId();
        if(userId == null){
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }

        Integer type = clubApplication.getType();
        QueryWrapper<ClubApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("result", ReviewResultEnum.WAITING.getCode()); //只查待审核的申请
        queryWrapper.eq("type", type);
        queryWrapper.eq("userId", userId);
        if (!type.equals(ApplicationTypeEnum.CREATE_CLUB.getCode())) {
            queryWrapper.eq("clubId", clubId);
        }
        return this.count(queryWrapper) > 0;
    }

    /**
     * 参数校验
     *
     * @param clubApplication
     */
    public void clubApplicationValidation(ClubApplication clubApplication) {
        Long clubId = clubApplication.getClubId();
        String reason = clubApplication.getReason();
        Integer applicationType = clubApplication.getType();
        String clubName = clubApplication.getClubName();
        String clubIntroduction = clubApplication.getClubIntroduction();
        String clubTags = clubApplication.getClubTags();

        if (!applicationType.equals(ApplicationTypeEnum.CREATE_CLUB.getCode()) && clubId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        if (StringUtils.isNotBlank(reason) && reason.length() > 2048){
            throw new BusinessException(ErrorCode.PARAM_ERROR, "申请原因过长");
        }
        if (!applicationType.equals(ApplicationTypeEnum.CREATE_CLUB.getCode()) &&
                !applicationType.equals(ApplicationTypeEnum.DELETE_CLUB.getCode()) &&
                !applicationType.equals(ApplicationTypeEnum.CHANGE_CLUB_INFO.getCode())) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "未知的申请类型");
        }
        if (applicationType.equals(ApplicationTypeEnum.CREATE_CLUB.getCode())) {
            Club club = new Club();
            club.setClubName(clubName);
            club.setIntroduction(clubIntroduction);
            clubService.clubValidation(club, true);
        }
        if (applicationType.equals(ApplicationTypeEnum.CHANGE_CLUB_INFO.getCode())) {
            Club club = new Club();
            club.setId(clubId);
            club.setClubName(clubName);
            club.setIntroduction(clubIntroduction);
            club.setTags(clubTags);
            clubService.clubValidation(club, false);
        }
    }

    /**
     * 获取查询条件
     *
     * @param clubApplicationQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<ClubApplication> getQueryWrapper(ClubApplicationQueryRequest clubApplicationQueryRequest) {
        QueryWrapper<ClubApplication> queryWrapper = new QueryWrapper<>();
        if (clubApplicationQueryRequest == null) {
            return queryWrapper;
        }

        Long id = clubApplicationQueryRequest.getId();
        Long userId = clubApplicationQueryRequest.getUserId();
        Long clubId = clubApplicationQueryRequest.getClubId();
        Integer type = clubApplicationQueryRequest.getType();
        Integer result = clubApplicationQueryRequest.getResult();
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(clubId), "clubId", clubId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(type), "type", type);
        queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
        queryWrapper.orderByDesc("createTime");  // 默认按创建时间降序排序
        return queryWrapper;
    }

    @Override
    public boolean addApplication(ClubApplicationAddRequest param) {
        ClubApplication clubApplication = new ClubApplication();
        clubApplication.setUserId(param.getUserId());
        clubApplication.setClubId(param.getClubId());
        clubApplication.setReason(param.getReason());
        clubApplication.setType(param.getType());
        clubApplication.setClubName(param.getClubName());
        clubApplication.setClubIntroduction(param.getClubIntroduction());
        clubApplication.setClubTags(param.getClubTags().toString());
        clubApplication.setNewManagerId(param.getNewManagerId());
        if(!this.save(clubApplication)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "申请操作失败");
        }
        return true;
    }

    @Override
    public Page<ClubApplicationListVO> getAllList(PageQueryRequest pageRequest) {
        Page<ClubApplication> page=new Page<>(pageRequest.getCurrent(),pageRequest.getPageSize());
        QueryWrapper<ClubApplication> queryWrapper =new QueryWrapper<>();
        if(pageRequest.getQuery()!=null){
            queryWrapper.like("id",pageRequest.getQuery());
        }
        page.setRecords(this.baseMapper.getClubApplication(page,queryWrapper));
        return convert(page);
    }

    @Override
    public boolean deleteClubApplication(List<Long> ids) {
        ids.forEach(id->{
            int i = this.getBaseMapper().deleteById(id);
            if(i==0){
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除操作失败");
            }
        });
        return true;
    }

    public Page<ClubApplicationListVO> convert(Page<ClubApplication> page) {
        List<ClubApplicationListVO> list = page.getRecords().stream().map(e -> {
            ClubApplicationListVO vo = new ClubApplicationListVO();
            BeanUtils.copyProperties(e, vo);
            try {
                String userName = userService.getById(e.getUserId()).getUserName();
                vo.setUserName(userName);
            }catch (NullPointerException nullePointerException){
                log.error("用户不存在");
                vo.setUserName(null);
            }
            return vo;
        }).toList();
        return new Page<ClubApplicationListVO>(page.getCurrent(),page.getSize()).setRecords(list).setTotal(page.getTotal());
    }
}




